import GraphVertex from '../res/data-structures/graph/GraphVertex.js';
import GraphEdge from '../res/data-structures/graph/GraphEdge.js';
import Graph from '../res/data-structures/graph/Graph.js';
import eulerianPath from '../res/graph/eulerian-path/eulerianPath.js';
import MathJax from './MathJax.js'
let exampleGraph=[
    {
       "nodeNum":8,
       "edgeList":[
            {
                "source":0,
                "target":1
            },
            {
                "source":1,
                "target":2
            },
            {
                "source":2,
                "target":3
            },
            {
                "source":3,
                "target":4
            },
            {
                "source":4,
                "target":5
            },
            {
                "source":5,
                "target":6
            },
            {
                "source":6,
                "target":7
            },
            {
                "source":7,
                "target":0
            }
        ] 
    },
     {
       "nodeNum":12,
       "edgeList":[
            {
                "source":0,
                "target":1
            },
            {
                "source":1,
                "target":2
            },
            {
                "source":2,
                "target":3
            },
            {
                "source":3,
                "target":4
            },
            {
                "source":4,
                "target":5
            },
            {
                "source":5,
                "target":6
            },
            {
                "source":6,
                "target":7
            },
            {
                "source":7,
                "target":0
            },
            {
                "source":7,
                "target":8
            },
            {
                "source":8,
                "target":9
            },
            {
                "source":9,
                "target":10
            },
            {
                "source":10,
                "target":11
            },
            {
                "source":11,
                "target":8
            }
        ] 
    }
];
function getOption(graphInfo){
//给节点设置样式
    let nodes=graphInfo['nodes'];
    let links=graphInfo['links'];
    //console.log(links);
//设置option样式
    return {
        title: {
            text: title,
            left: 'center',
            textStyle:{
                fontSize:20
            },
            bottom:20
        },
        tooltip: {
            trigger: 'item'
        },
        backgroundColor:'white',
        roam: true,
        series: [
            {
                type: 'graph',
                layout: 'force',
                force:{
                    repulsion : 200, edgeLength:[50,100]
                },
                ribbonType: false,
                symbol: "circle",
                edgeSymbol:['none', 'none'],
                symbolSize: 27,
                edgeSymbolSize: 10,
                nodes: nodes,
                links: links,
                label: {
                    normal: {
                        show: true
                    }
                },
                draggable:true
            }
        ]
    };
}
function nodeStyle(title){
   return  { 
       name: title,
       itemStyle: {borderColor: 'black',color:'white',borderWidth: 3},
       label:{
           show:true,
           position:'inside',
           fontSize:15,
           color:'black',
           fontWeight:'bold'
        }
    }
}
function edgeStyle(selectNode){
    matrix[selectNode[0]][selectNode[1]]=1;
    matrix[selectNode[1]][selectNode[0]]=1;
    return {
        source: selectNode[0],
        target: selectNode[1],
        value:100,
        lineStyle: {
            width: 5,
            color: '#000',
            type:'solid',
            opacity:0.8,
            ignoreForceLayout:true,
            select:{
                lineStyle:{
                    color:selectColor
                }
            }
        }
    };
}
function getNodes(Num){
    let nodes=[];
    let nodeTitle=['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
    for(let i=0;i< Num;i++){
        let str="";
        for(let j=0;j<=parseInt(i/26);j++){
           // console.log(i-parseInt(i/26)*26);
            str+=nodeTitle[i-parseInt(i/26)*26];
        }
        nodes.push(nodeStyle(str))
        matrix[i]=[];
        for(let k=0;k<Num;k++){
            matrix[i][k]=0;
        }
    }

    //console.log(nodes);
    return nodes;
}
function getSampleLinks(){
    let links1=[];
    links1.push(edgeStyle([1,3]))
    links1.push(edgeStyle([2,3]))
    links1.push(edgeStyle([2,4]))
    links1.push(edgeStyle([4,5]))
    links1.push(edgeStyle([5,7]))
    links1.push(edgeStyle([2,6]))
    links1.push(edgeStyle([6,7]))
    return links1;
}
function getLoadLinks(json1){
    let links1=[];
    let len=json1.length;
    for(let i=0;i<len;i++){
        for(let j=i+1;j<len;j++){
            if(json1[i][j]==1) links1.push(edgeStyle([i,j]));
        }
    }
    return links1;
}
function TransitiveClosure(dist)//寻找可达矩阵
{
    let t=[];
    let N=dist.length;
	for(let i=0;i<N;i++)//进行遍历
    {
        t[i]=[];
		for(let j=0;j<N;j++)
		{
			if((i==j)||(dist[i][j])==1)//发现可达
				t[i][j]=1;
			else
				t[i][j]=0;
		}
    }
    let flag=true;
    isConnected=true;
	for(let k=0;k<N;k++)
		for(let i=0;i<N;i++){
			for(let j=0;j<N;j++)
				t[i][j]=t[i][j]||(t[i][k]&&t[k][j]);//由文中公式可得
        }
    for(let k=0;k<N;k++)
		for(let i=0;i<N;i++){
        if(t[k][i]==0&&flag==true){
            isConnected=false;
            flag=false;
        }
    } 
    return t;    
}
//由字母获取 下标  eulerianPathSet转 每一条边 逐步显示
function getIndex(letter){
  let nodeTitle=['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
  let len=letter.length;
  let l=letter[0];
  let index=getArrayIndex(nodeTitle,l);
  return index+26*(len-1);
}
function getArrayIndex(arr, obj) {
    var i = arr.length;
    while (i--) {
        if (arr[i] === obj) {
            return i;
        }
    }
    return -1;
}
function judgeEuler(){
    title="";
    let vertexList=[];
    const graph = new Graph();
    for(let i=0;i<nodes.length;i++){
        let obj=new GraphVertex(nodes[i].name);
        vertexList.push(obj);
        graph.addVertex(obj);
    }
    //console.log(links);
    //console.log(vertexList);
    for(let j=0;j<links.length;j++){
        graph.addEdge(new GraphEdge(vertexList[links[j].source], vertexList[links[j].target]))
    }
    //console.log(graph);
    const graphEdgesCount = graph.getAllEdges().length;
    console.log(graphEdgesCount);
    try{
        eulerianPathSet = eulerianPath(graph);
        eulerIndex=0;
    }catch(e){
        console.log(e);
        isEuler=false;
    }
    if(isConnected){
        title+="连通图";
        if(isEuler){
            title+="-欧拉图\n"+" \n"
            for(let i=0;i<eulerianPathSet.length;i++){
                if(i==0) title+=eulerianPathSet[i].value
                else title+="-"+ eulerianPathSet[i].value
            }
            modalApp.modalAlert('欧拉回路生成成功，请点击显示路径');
        }
        else{
            if(isEulerPath){
                title+="-欧拉道路\n"+" \n";
                for(let i=0;i<eulerianPathSet.length;i++){
                    if(i==0) title+=eulerianPathSet[i].value
                    else title+="-"+ eulerianPathSet[i].value
                }
                modalApp.modalAlert('欧拉道路生成成功，请点击显示路径');
            }
            else{
                modalApp.modalAlert('没有欧拉道路和回路');
                title+="-没有欧拉道路和回路";
                return;
            }
        }
    }
    else {
        // title+="非连通图";
        // if(isEuler){
        //      title+="-最大子连通图-\n"+" \n";
        //      for(let i=0;i<eulerianPathSet.length;i++){
        //             if(i==0) title+=eulerianPathSet[i].value
        //             else title+="-"+ eulerianPathSet[i].value
        //     }
        // }
        // else{
        //     title+="最大子连通图没有欧拉路径和回路"
        // }
        modalApp.modalAlert('不连通,不存在欧拉通路和欧拉回路');return;
        return;
    }
    option.title.text=title;
    myChart.setOption(option);
    $('#showEuler').click();
}
function showLinksRed(index1,index2){
    let index=0;
    for(let i=0;i<links.length;i++){
        if((links[i].source==index1&&links[i].target==index2)||(links[i].source==index2&&links[i].target==index1))
        {
            index=i;
            break;
        }
    }
    option.series[0].links[index].lineStyle.color=eulerEdgeColor;
    option.series[0].links[index].lineStyle.width=10;
    myChart.setOption(option);
}
function initData(){
    nodes=[],links=[],option={};
    matrix=[];
    isEuler=true;
    isEulerPath=false;
    isConnected=true;
    title="";
    eulerianPathSet;
    eulerIndex=0;//显示欧拉的边的下标
    eulerEdgeColor="#ff0000"
    selectColor='#007bff',selectborderColor='white',Edgecolor='black';
    color='white',borderColor='black';
    selectNodeNum=0,selectNode=[],selectEdge=0,selectEdgeIndex=-1; //被选节点数量和下标
}
let myChart = echarts.init(document.getElementById('echartsDiv'));
let nodes=[],links=[],option={};
let matrix=[];
let isEuler=true;
let isEulerPath=false;
let isConnected=true;
let title="";
let eulerianPathSet;
let eulerIndex=0;//显示欧拉的边的下标
let eulerEdgeColor="#ff0000"
let selectColor='#007bff',selectborderColor='white',Edgecolor='black';
let color='white',borderColor='black';
let selectNodeNum=0,selectNode=[],selectEdge=0,selectEdgeIndex=-1; //被选节点数量和下标
var app = new Vue({
  el: '#app',
  data: {
    reachableList:[],
    nodeList:[],
    showMatrix:false,
    examples:["样例1","样例2"],
    matrix1:"",
    matrix2:""
  },
  methods: {
      dealNodeList(){
        this.nodeList=[];
        let jiDu=0;
        //计算邻接矩阵
        for(let i=0;i<nodes.length;i++){
            let du=0;
            for(let j=0;j<nodes.length;j++){
                du+=matrix[i][j];
            }
            //判断欧拉图的条件为 无向图没有奇点
            if(du%2==1&&isEuler) isEuler=false;
            if(du%2==1){
                jiDu++;
            }
            this.nodeList.push({
                title:nodes[i].name,
                du:du,
                content:matrix[i].toString()
            });
            this.showMatrix=true;
        }
        if(!isEuler&&jiDu<=2) isEulerPath=true;
        else isEulerPath=false;
      },
      setShowMatrix(){
        console.log("0")
        this.showMatrix=false;
      },
      dealReachableList(){
         //计算可达性矩阵
        this.reachableList=[];
        let dist=TransitiveClosure(matrix);
        let matrixs1="$$\\begin{bmatrix}",matrixs2="$$\\begin{bmatrix}";
            for(let i=0;i<matrix.length;i++){
                for(let j=0;j<matrix[i].length;j++){
                    if(j!=(matrix[i].length-1)) {
                        matrixs1+=" "+matrix[i][j]+" &";
                        matrixs2+=" "+dist[i][j]+" &"
                    }
                    else {
                        matrixs1+=" "+matrix[i][j]+" \\\\";
                        matrixs2+=" "+dist[i][j]+" \\\\";
                    }

            }
        }
        matrixs1+="\\end{bmatrix}$$";matrixs2+="\\end{bmatrix}$$";
        document.getElementById("matrix1").innerHTML= "";
        document.getElementById("matrix2").innerHTML= "";
        this.matrix1=matrixs1;
        this.matrix2=matrixs2;
        document.getElementById("matrix1").innerHTML= matrixs1;
        document.getElementById("matrix2").innerHTML= matrixs2;
        this.formatMath1(); 
      },
      showGraphExamples(index){
        //显示样例
        initData();
        let graph=exampleGraph[index];
        nodes=getNodes(graph.nodeNum);
        let l=graph.edgeList;
        for(let i=0;i<l.length;i++){
            links.push(edgeStyle([l[i].source,l[i].target]));
        }
        let jsonData={"nodes":nodes,"links":links}
        option=getOption(jsonData);
        myChart.setOption(option);
      },
      formatMath1() {
            let that = this;
            console.log(MathJax);
            that.$nextTick(function () {
                if(MathJax.isMathjaxConfig){//判断是否初始配置，若无则配置。
                    MathJax.initMathjaxConfig();
                }
                MathJax.MathQueue("app");//传入组件id，让组件被MathJax渲染
            })
      }
  },
})
var modalApp=new Vue({
    el:"#myModal1",
    data:{
        message:""
    },
    methods:{
        modalAlert(str){
            this.message=str;
            $('#myModal1').modal('toggle');
        }
    }
})

$("#submitBtn").click(function(){
         var results = $(".form-inline").serializeArray();
         var data=[];
         isEuler=true;title="";
         $.each(results,function(index,item){
            //文本表单的值不为空才处理
            if(item.value && $.trim(item.value)!=""){
            if(!data[item.name]){
               data[item.name]=item.value;
            }
            else{
              data[item.name]=data[item.name]+','+item.value;
            }
            }
        });
        //节点数量
        let Num=parseInt(data["NodeNum"]);
        console.log(Num);
        if(Num!=NaN){
            selectNodeNum=0,selectNode=[],selectEdge=0,selectEdgeIndex=-1;
            nodes=[],links=[],option={};
            nodes=getNodes(Num);
            //创建点
            //创建样本边方便测试
           // links=getSampleLinks();
            let jsonData={"nodes":nodes,"links":links}
            //数据格式为Json格式
            option=getOption(jsonData);
            //console.log(option);
            //console.log(myChart);
            //使用Option填充图形
            myChart.setOption(option);
        }
        else{
            modalApp.modalAlert('输入有误');
        }
});
myChart.on('click', function (params) {
    console.log(params);
    if(params.dataType=='node'){
        if(selectNodeNum<2){
            if(option.series[0].nodes[params.dataIndex].itemStyle.color==selectColor){
                option.series[0].nodes[params.dataIndex].itemStyle.color=color;
                option.series[0].nodes[params.dataIndex].itemStyle.borderColor=borderColor;
                option.series[0].nodes[params.dataIndex].label.color='black';
                selectNode=[];
                selectNodeNum--;
            }
            else{
                option.series[0].nodes[params.dataIndex].itemStyle.color=selectColor
                option.series[0].nodes[params.dataIndex].itemStyle.borderColor=selectborderColor;
                option.series[0].nodes[params.dataIndex].label.color='white';
                if(selectNodeNum==0) selectNode[0]=params.dataIndex;
                if(selectNodeNum==1) selectNode[1]=params.dataIndex;
                console.log('selectNode-'+selectNode);
                selectNodeNum++;
                    
            }
                //如果选择的节点在2个以下，可以选择
                myChart.setOption(option);
        }
        else{
            if(option.series[0].nodes[params.dataIndex].itemStyle.color==selectColor){
                option.series[0].nodes[params.dataIndex].itemStyle.color=color;
                option.series[0].nodes[params.dataIndex].itemStyle.borderColor=borderColor;
                option.series[0].nodes[params.dataIndex].label.color='black';
                let selectNode1=[];
                if(selectNode[0]==params.dataIndex) selectNode1[0]=selectNode[1];
                if(selectNode[1]==params.dataIndex) selectNode1[0]=selectNode[0];
                    selectNode=selectNode1;
                    console.log('selectNode-'+selectNode);
                    selectNodeNum--;
                    myChart.setOption(option);
                }
                else{
                    modalApp.modalAlert('已选择了两个点了！');
                }
        }
    }
    else if(params.dataType=='edge'){
      console.log(selectEdge);
      if(selectEdge==0){
          option.series[0].links[params.dataIndex].lineStyle.color=selectColor;
          myChart.setOption(option);
          selectEdge++;selectEdgeIndex=params.dataIndex;
      }
      else{
          if(option.series[0].links[params.dataIndex].lineStyle.color==selectColor){
             option.series[0].links[params.dataIndex].lineStyle.color=Edgecolor;
             myChart.setOption(option);
             selectEdge--;params.dataIndex=-1;
          }
          else{
              modalApp.modalAlert('已选择了一条边，请取消后再选择！');
          }
      }
    }
            
});
$('#addLine').click(()=>{
    if(selectNodeNum==2){
        option.series[0].links.push(edgeStyle(selectNode));
        option.series[0].nodes[selectNode[0]].itemStyle.color=color;
        option.series[0].nodes[selectNode[0]].itemStyle.borderColor=borderColor;
        option.series[0].nodes[selectNode[0]].label.color='black';
        option.series[0].nodes[selectNode[1]].itemStyle.color=color;
        option.series[0].nodes[selectNode[1]].itemStyle.borderColor=borderColor;
        option.series[0].nodes[selectNode[1]].label.color='black';
        selectNodeNum=0,selectNode=[];
        myChart.setOption(option);
    }
    else{
       modalApp.modalAlert('未选择两个点');
    }
})
$('#subLine').click(()=>{
    if(selectEdge>0){
        let edgeI=option.series[0].links[selectEdgeIndex];
        matrix[edgeI.source][edgeI.target]=0;
        matrix[edgeI.target][edgeI.source]=0;
        option.series[0].links.splice(selectEdgeIndex,1);
        myChart.setOption(option);
        selectEdge=0;selectEdgeIndex=-1;
    }
    else{
        modalApp.modalAlert('未选择边');
    }
})
$('#huiLine').click(()=>{
    if(nodes.length==0) {
        modalApp.modalAlert('请先生成图');
        return;
    }
    console.log("huiLine");
    app.dealNodeList();
    app.dealReachableList();
    judgeEuler();
})
$('#showEuler').click(()=>{

    if(isEuler||isEulerPath){
        //逐步显示
        eulerIndex++;
        if(eulerIndex==eulerianPathSet.length){
            modalApp.modalAlert('已显示完毕');
        }
        else{
            let index1=getIndex(eulerianPathSet[eulerIndex].value);
            let index2=getIndex(eulerianPathSet[eulerIndex-1].value);
            showLinksRed(index1,index2);
        }
    }
    else{
        modalApp.modalAlert('不存在欧拉回路和欧拉道路');
    }
})
$('#zhongzhi').click(()=>{
    //重置显示
    for(let i=0;i<links.length;i++){
        links[i].lineStyle.color=Edgecolor;
        links[i].lineStyle.width=5;
    }
    app.setShowMatrix();
    myChart.setOption(option);
})
$('#loadData').click(()=>{
    //导入excel数据
    $('#txt_file').click();
})
document.getElementById("txt_file").addEventListener('change', handleFile, false);
function handleFile(e){
    var files = e.target.files, f = files[0];
    var reader = new FileReader();
    reader.onload = function(e) {
        let myWorkBook;
        var data = new Uint8Array(e.target.result);
        myWorkBook= XLSX.read(data, {type: 'array'});
        console.log(myWorkBook);
        let json1=XLSX.utils.sheet_to_json(myWorkBook.Sheets[myWorkBook.SheetNames[0]],{header:1});
        console.log(json1);
        initData();
        let Num=json1.length;
        nodes=getNodes(Num);
        //创建点
        //创建样本边方便测试
        links=getLoadLinks(json1);
        let jsonData={"nodes":nodes,"links":links}
        //数据格式为Json格式
        option=getOption(jsonData);
        //console.log(option);
        //console.log(myChart);
        //使用Option填充图形
        myChart.setOption(option);
    }
    reader.readAsArrayBuffer(f);
}
